package com.zm.admin.zmeng.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zm.admin.utils.ResultBean;
import com.zm.admin.utils.ServletUtil;
import com.zm.admin.zmeng.domain.ZmAttachment;
import com.zm.admin.zmeng.mapper.ZmAttachmentMapper;
import com.zm.admin.zmeng.mapper.ZmUserMapper;
import com.zm.admin.zmeng.service.ZmAttachmentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/***
 *
 * @Auther: MuYun
 * @Date: 2023/2/6 10:43
 * @Description：附件service实现类
 *
 */
@Service
@Slf4j
@Transactional(rollbackFor = { Exception.class })
public class ZmAttachmentServiceImpl extends ServiceImpl<ZmAttachmentMapper, ZmAttachment> implements ZmAttachmentService {

    @Resource
    private ZmUserMapper zmUserMapper;

    @Resource
    private ZmAttachmentMapper zmAttachmentMapper;

    @Override
    public String upload(HttpServletRequest request, MultipartFile file, String type) throws Exception {
        ZmAttachment attachment = initAttachment(file, type);
        File uploadFile=new File(attachment.getAbsolutePath());
        //目录不存在则新建
        FileUtil.mkParentDirs(uploadFile);
        //上传
        file.transferTo(uploadFile);
        //回传给前端的图片url,http://localhost:8082/upload/img/202302066962.JPG
        String urlPath="/upload/"+LocalDate.now()+"/"+attachment.getFileName();
        attachment.setUrlPath(urlPath);
        attachment.setFileSize(getPrintSize(file.getSize()));
        zmAttachmentMapper.insert(attachment);
        return urlPath;
    }

    @Override
    public void download(ZmAttachment attachment) throws Exception {
        ZmAttachment zmAttachment = zmAttachmentMapper.selectById(attachment.getId());
        if(ObjectUtil.isEmpty(zmAttachment)){
            attachment=new ZmAttachment();
            attachment.setAbsolutePath("");
        }
        HttpServletResponse response = ServletUtil.getResponse();
        File file=new File(zmAttachment.getAbsolutePath());
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.setHeader("content-disposition",
                "attachment;filename=" + URLEncoder.encode(zmAttachment.getOriginalName(), "UTF-8"));
        if(file.exists()){
            FileCopyUtils.copy(new FileInputStream(file),response.getOutputStream());
        }
    }

    @Override
    public ResultBean del(List<ZmAttachment> list){
        ResultBean resultBean=new ResultBean();
        try{
            zmAttachmentMapper.deleteBatchIds(list.stream().map(ZmAttachment::getId).collect(Collectors.toList()));
            for(ZmAttachment attachment:list){
                FileUtil.del(attachment.getAbsolutePath());
            }
            resultBean.setCode(ResultBean.CODE_SUCCESS).setMsg("文件删除成功！");
        }catch (Exception e){
            log.error("文件删除接口报错:{}",e);
            resultBean.setData(ResultBean.CODE_ERROR).setMsg("文件删除接口报错");
            throw e;
        }
        return resultBean;
    }

    /**
     * 获取web路径
     * @param request
     * @return
     */
    /*static String getReqUrl(HttpServletRequest request){
        return request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort();
    }*/

    /**
     * 根据文件初始化与其对应的附件实体
     * @param file
     * @param type
     * @return
     */
    public ZmAttachment initAttachment(MultipartFile file,String type){
        ZmAttachment attachment=new ZmAttachment();
        String filefullname = file.getOriginalFilename();
        //logger.info("原文件名：{}",filefullname);
        String root = System.getProperty("user.dir");
        //log.info("根路径：{}",root);//D:\JavaProjects\zmAdmin\zm-springboot-admin
        //获取拓展名
        String fileExtname = filefullname.substring(filefullname.lastIndexOf(".") + 1).toUpperCase();

        List<String> extList = new ArrayList<String>(Arrays.asList("png", "jpg", "peg", "bmp", "gif", "webp", "psd", "svg", "tiff"));
        for(String str:extList){
            if(str.equalsIgnoreCase(fileExtname)){
                attachment.setIsShow(true);
                break;
            }else{
                attachment.setIsShow(false);
            }
        }
        SimpleDateFormat format=new SimpleDateFormat("yyyyMMdd");
        //新文件名
        String newFilename=format.format(new Date())+new Random().nextInt(10000)+'.'+fileExtname;
        //文件全路径
        String path=root+"/upload/"+ LocalDate.now() +"/"+newFilename;
        //log.info("看看path:{}",path);//D:\JavaProjects\zmAdmin\zm-springboot-admin//upload/img/202302066962.JPG
        attachment.setAbsolutePath(path);
        attachment.setOriginalName(filefullname);
        attachment.setFileName(newFilename);
        attachment.setFileType(fileExtname);
        attachment.setType(type);
        attachment.setCreateBy(StpUtil.getLoginIdAsString());
        attachment.setCreateTime(DateUtil.date());
        return attachment;
    }

    /**
     * 返回文件大小
     * @param size
     * @return
     */
    static String getPrintSize(long size) {
        // 如果字节数少于1024，则直接以B为单位，否则先除于1024，后3位因太少无意义
        if (size < 1024) {
            return size + "B";
        } else {
            size = size / 1024;
        }
        // 如果原字节数除于1024之后，少于1024，则可以直接以KB作为单位
        // 因为还没有到达要使用另一个单位的时候
        // 接下去以此类推
        if (size < 1024) {
            return size + "KB";
        } else {
            size = size / 1024;
        }
        if (size < 1024) {
            // 因为如果以MB为单位的话，要保留最后1位小数，
            // 因此，把此数乘以100之后再取余
            size = size * 100;
            return size / 100 + "." + size % 100 + "MB";
        } else {
            // 否则如果要以GB为单位的，先除于1024再作同样的处理
            size = size * 100 / 1024;
            return size / 100 + "." + size % 100 + "GB";
        }
    }
}
